package com.lsa.letcode.the7.reverse;

public class Solution {
	public int reverse(int x) {
		if (x == Integer.MIN_VALUE) {
			return 0;
		}
		if (Math.abs(x) < 10) {
			return x;
		}
		
		boolean isNegative = x < 0;
		if (isNegative) {
			x = -x;
		}
		
		int reversed = 0;
		
		try{
			while(x != 0) {
				int leftDigit = x % 10;
				reversed = add(mul(reversed, 10), leftDigit);
				x /= 10;
			}
		}
		catch(ArithmeticException e) {
        	return 0;
        }
		
		if (isNegative) {
			reversed = -reversed;
		}
		
		return reversed;
	}
	public int reverse2TwoSides(int x) {
		if (x == Integer.MIN_VALUE) {
			return 0;
		}
		if (Math.abs(x) < 10) {
			return x;
		}
		
		boolean isNegative = x < 0;
		if (isNegative) {
			x = -x;
		}
		
		//2143847412
		//1000000000
		
		int reversed = 0;
        try{
            int leftFactor = 10;
            if (x >= 1000000000) {
            	leftFactor = 1000000000;
            }
            else {
            	while( leftFactor * 10 <= x ) {
            		leftFactor *= 10;
            	}
            }
            
            int leftPower = leftFactor;
            int rightPower = 1;
        	while(leftPower >= rightPower) {
        		int leftDigit = x / leftFactor;
        		int rightDigit = x % 10;
        		
        		reversed = add(reversed, mul(leftPower , rightDigit));
        		
        		if (leftPower > rightPower) {
        			reversed = add(reversed, mul(rightPower , leftDigit));
        		}
        		
        		// 12345 -> 234 -> 3
        		// 1234567 -> 23456 -> 345 -> 4
        		x -= leftFactor * leftDigit;
        		x /= 10; 
        		
        		leftFactor /= 100;
        		
        		leftPower /= 10;
        		rightPower *= 10;
        	}
        }
        catch(ArithmeticException e) {
        	return 0;
        }
        
        if (isNegative) {
        	reversed = -reversed;
		}
        
        return reversed;
    }
	
	private int mul(int a, int b) {
		if (a != 0 && b > Integer.MAX_VALUE / a) {
			throw new ArithmeticException();
		}
		
		return a * b;
	}
	
	private int add(int a, int b) {
		if (a != 0 && b > Integer.MAX_VALUE - a) {
			throw new ArithmeticException();
		}
		
		return a + b;
	}
}